home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 401-425 / disk_408 / post / post13.lzh / Post / source / postlj.c < prev   
C/C++ Source or Header  |  1990-10-27  |  16KB  |  646 lines

  1. /* LaserJet print driver for Post V1.3.  File "postlj.c"
  2.  * (C) Adrian Aylward 1989, 1990
  3.  *
  4.  * You may freely copy, use, and modify this file.
  5.  *
  6.  * This program prints PostScript files to a LaserJet.  It sends the output
  7.  * to the PAR: handler.  Page size and orientation are read from the command
  8.  * line.  There are no printer status checks; if the output hangs check your
  9.  * printer is ready.  It is totally Amiga specific.
  10.  *
  11.  * The program was tested using Lattice C V5.05.  It has various Lattice
  12.  * dependencies.
  13.  */
  14.  
  15. # include <dos.h>
  16. # include <devices/printer.h>
  17. # include <devices/prtbase.h>
  18. # include <exec/exec.h>
  19. # include <exec/execbase.h>
  20. # include <exec/tasks.h>
  21. # include <graphics/gfx.h>
  22. # include <graphics/rastport.h>
  23. # include <proto/dos.h>
  24. # include <proto/exec.h>
  25. # include <string.h>
  26. # include <stdio.h>
  27. # include <fcntl.h>
  28. # include <ios1.h>
  29.  
  30. # include "postlib.h"
  31.  
  32. /* Assembler routines */
  33.  
  34. extern void insertbreak(void);
  35. extern void deletebreak(void);
  36. extern void insertftrap(void);
  37. extern void deleteftrap(void);
  38.  
  39. /* Routines defined and referenced only within this module */
  40.  
  41. extern int  strtoint(char **sp, int *ip);
  42. extern void __saveds __asm copypage(register __d0 int num);
  43. extern void prtsetup(void);
  44. extern void prtreset(void);
  45. extern void prtdump(int copies);
  46. extern void prtdumpline(char *buf, int len);
  47.  
  48. /* Lattice startup */
  49.  
  50. extern struct UFB _ufbs[];
  51.  
  52. /* External data (initialised to zero) */
  53.  
  54. int retcode;
  55.  
  56. int arec;
  57.  
  58. BPTR errfh;
  59. FILE *parfp;
  60.  
  61. struct library *PSbase;
  62. struct PSparm parm;
  63.  
  64. int breakset, ftrapset;
  65.  
  66. /* Options */
  67.  
  68. # define DEFSIZE 3 /* A4 page size */
  69. # define DEFLAND 0 /* Portrait orientation */
  70. # define DEFCOMP 1 /* Allow graphics compression (LJ2P etc.) */
  71.  
  72. # define MAXSIZE 8
  73.  
  74. int optsize = DEFSIZE;
  75. int optland = DEFLAND;
  76. int optcomp = DEFCOMP;
  77. int optcopies;
  78. int optbeg, optend;
  79.  
  80. int pagenum;
  81.  
  82. /* Page size tables.
  83.  * (See Figures 2-2 and 2-3 in the LaserJet 2P Technical Reference Manual.)
  84.  *
  85.  *                     Let   Legal Exec  A4    COM10 Mon   C5    DL
  86.  */
  87.  
  88. int psize[MAXSIZE] = {    2,    3,    1,   26,   81,   80,   91,   90 };
  89.  
  90. int xsize[MAXSIZE] = { 2550, 2550, 2175, 2480, 1237, 1162, 1913, 1299 };
  91. int ysize[MAXSIZE] = { 3300, 4200, 3150, 3507, 2850, 2250, 2704, 2598 };
  92. int ppoff[MAXSIZE] = {   75,   75,   75,   71,   75,   75,   71,   71 };
  93. int ploff[MAXSIZE] = {   60,   60,   60,   59,   60,   60,   59,   59 };
  94.  
  95. char *showsize[MAXSIZE] = {"letter", "legal", "executive", "A4",
  96.                            "COM-10", "monarch", "C5", "DL" };
  97. char *showland[2] = {"portrait", "landscape" };
  98.  
  99. int compsize;
  100. char *compbuf;
  101.  
  102. /* Arguments */
  103.  
  104. char *argto = "par:";
  105. int argfilec, argmemc;
  106. char *argfilev[5], *argmemv[5];
  107. char *argkey[] =
  108. {   "TO", "MEM", NULL };
  109.  
  110. /* Startup code */
  111.  
  112. extern void main(int argc, char **argv);
  113.  
  114. void _main(char *line)
  115. {   char *argv[32];
  116.     int argc;
  117.  
  118.     /* Parse the arguments to break words and strip quotes.  N.B. the
  119.      * main program can determine that the arument was quoted by inspecting
  120.      * the preceeding character */
  121.  
  122.     argc = 0;
  123.     if (line == NULL) goto endline;
  124.     for (;;)
  125.     {   while (*line == ' ' || *line == '\t' || *line == '\n') line++;
  126.         if (*line == 0) break;
  127.         if (argc == 32)
  128.         {   argc = 0;
  129.             goto endline;
  130.         }
  131.         if (*line == '"')
  132.         {   argv[argc] = ++line;
  133.             while (*line != '"')
  134.             {   if (*line == 0)
  135.                 {   argc = 0;
  136.                     goto endline;
  137.                 }
  138.                 line++;
  139.             }
  140.         }
  141.         else
  142.         {   argv[argc] = line;
  143.             while (*line != ' ' && *line != '\t' && *line != '\n')
  144.             {   if (*line == 0)
  145.                 {   argc++;
  146.                     goto endline;
  147.                 }
  148.                 line++;
  149.             }
  150.         }
  151.         *line++ = 0;
  152.         argc++;
  153.     }
  154. endline:
  155.  
  156.     /* Set up the standard input/output files */
  157.  
  158.     errfh = Open("*", MODE_OLDFILE);
  159.     if (errfh == NULL)
  160.     {   retcode = 20;
  161.         goto tidyexit;
  162.     }
  163.     _ufbs[2].ufbfh = (long) errfh;
  164.     _ufbs[2].ufbflg |= UFB_WA|O_RAW|UFB_NC;
  165.     stderr->_file = 2;
  166.     stderr->_flag = _IOWRT;
  167.     setbuf(stderr, NULL);
  168.  
  169.     /* Call the main program  */
  170.  
  171.     main(argc, argv);
  172.  
  173.     /* Tidy up and exit */
  174.  
  175. tidyexit:
  176.     if (errfh) Close(errfh);
  177.  
  178.     XCEXIT(retcode);
  179. }
  180.  
  181. /* Main program */
  182.  
  183. void main(int argc, char **argv)
  184. {   char *s, *t;
  185.     int *ip, i, m, n, ch;
  186.  
  187.     /* Open the libraries */
  188.  
  189.     PSbase = OpenLibrary("post.library", 0);
  190.     if (PSbase == NULL)
  191.     {   fprintf(stderr, "postlj: can't open post.library\n");
  192.         goto errorexit;
  193.     }
  194.  
  195.     /* Parse the arguments and keywords.  See the usage string below */
  196.  
  197.     argc--;
  198.     argv++;
  199.     if (argc == 0 || (argc == 1 && strcmp(*argv, "?") == 0)) goto usage;
  200.  
  201.     while (argc--)
  202.     {   s = *argv++;
  203.         i = -1;
  204.         if (s[-1] != '"')
  205.             if (*s == '-')
  206.             {   s++;
  207.                 while (t = s, ch = *s++)
  208.                 {   switch (ch)
  209.                     {   case 'S': case 's':
  210.                            m = MAXSIZE;
  211.                            ip = &optsize;
  212.                            break;
  213.     
  214.                         case 'L': case 'l':
  215.                            m = 2;
  216.                            ip = &optland;
  217.                            break;
  218.     
  219.                         case 'B': case 'b':
  220.                            m = 10000;
  221.                            ip = &optbeg;
  222.                            break;
  223.  
  224.                         case 'E': case 'e':
  225.                            m = 10000;
  226.                            ip = &optend;
  227.                            break;
  228.  
  229.                         case 'N': case 'n':
  230.                            m = 100;
  231.                            ip = &optcopies;
  232.                            break;
  233.     
  234.                         case 'C': case 'c':
  235.                            m = 2;
  236.                            ip = &optcomp;
  237.                            break;
  238.  
  239.                         default:
  240.                            fprintf(stderr,
  241.                                    "postlj: unknown option \"%c\"\n", ch);
  242.                            goto badusage;
  243.                     }
  244.                     if (!strtoint(&s, &i)) goto badvalue;
  245.                     if ((unsigned) i >= m)
  246.                     {   fprintf(stderr,
  247.                                 "postlj: option value out of range "
  248.                                 "(0-%d) \"%.*s\"\n", m - 1, s - t, t);
  249.                         goto errorexit;
  250.                     }
  251.                     *ip = i;
  252.                 }
  253.                 continue;
  254.             }
  255.             else
  256.                 for (;;)
  257.                 {   i++;
  258.                     if (argkey[i] == NULL)
  259.                     {   i = -1;
  260.                         break;
  261.                     }
  262.                     if (stricmp(s, argkey[i]) == 0) break;
  263.                 }
  264.         switch (i)
  265.         {   case  0:    /* TO */
  266.                 if (argc == 0) goto badargs;
  267.                 argc--;
  268.                 argto = *argv++;
  269.                 break;
  270.  
  271.             case  1:    /* MEM */
  272.                 if (argc == 0) goto badargs;
  273.                 argc--;
  274.                 if (argmemc == 5) goto badargs;
  275.                 argmemv[argmemc++] = *argv++;
  276.                 break;
  277.  
  278.             default:
  279.                 if (argfilec == 5) goto badargs;
  280.                 argfilev[argfilec++] = s;
  281.         }
  282.     }
  283.  
  284.     /* Set up the default memory sizes */
  285.  
  286.     parm.memvlen = 600000;
  287.     parm.memflen =  60000;
  288.     parm.memllen =  60000;
  289.     parm.memhlen =  20000;
  290.  
  291.     /* Parse the "MEM fhlv.." options */
  292.  
  293.     for (i = 0; i < argmemc; i++)
  294.     {   s = argmemv[i];
  295.         for (;;)
  296.         {   ch = *s++;
  297.             if (ch == 0) break;
  298.             ch = tolower(ch);
  299.             switch (ch)
  300.             {   case 'f':
  301.                     ip = &parm.memflen;
  302.                     break;
  303.  
  304.                 case 'h':
  305.                     ip = &parm.memhlen;
  306.                     break;
  307.  
  308.                 case 'l':
  309.                     ip = &parm.memllen;
  310.                     break;
  311.  
  312.                 case 'v':
  313.                     ip = &parm.memvlen;
  314.                     break;
  315.  
  316.                 default:
  317.                     goto badvalue;
  318.             }
  319.             if (!strtoint(&s, ip)) goto badvalue;
  320.         }
  321.     }
  322.  
  323.     /* Determine the page size */
  324.  
  325.     if (optland)
  326.     {   n = xsize[optsize];
  327.         m = ysize[optsize];
  328.     }
  329.     else
  330.     {   m = xsize[optsize];
  331.         n = ysize[optsize];
  332.     }
  333.     parm.page.depth = 1;
  334.     parm.page.xoff = parm.page.yoff = 0;
  335.     parm.page.xsize = m;
  336.     parm.page.ysize = n;
  337.     parm.page.xbytes = (parm.page.xsize + 7) >> 3;
  338.     parm.page.len = parm.page.xbytes * parm.page.ysize;
  339.     parm.page.ybase = 0;
  340.     parm.page.yheight = parm.page.ysize;
  341.     parm.page.xden = parm.page.yden = 300;
  342.     parm.page.ydir = -1;
  343.  
  344.     /* Allocate the page buffer */
  345.  
  346.     for (i = 0; i < parm.page.depth; i++)
  347.     {   if ((parm.page.buf[i] =
  348.                 AllocMem(parm.page.len, MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
  349.         {   fprintf(stderr, "postlj: can't get page buffer\n");
  350.             goto errorexit;
  351.         }
  352.     }
  353.  
  354.     /* Allocate the print compression buffer */
  355.  
  356.     compsize = parm.page.xbytes + parm.page.xbytes / 128 + 2;
  357.     compbuf = AllocMem(compsize, MEMF_PUBLIC);
  358.     if (compbuf == NULL)
  359.     {   fprintf(stderr, "postlj: can't get memory\n");
  360.         goto errorexit;
  361.     }
  362.  
  363.     /* Open a file to the par: handler and initialise the printer */
  364.  
  365.     parfp = fopen(argto, "w");
  366.     if (parfp == NULL)
  367.     {   fprintf(stderr, "postlj: can't get open %s\n", argto);
  368.         goto errorexit;
  369.     }
  370.     prtsetup();
  371.     if (ferror(parfp))
  372.     {   fprintf(stderr, "postlj: error writing printer file\n");
  373.         goto errorexit;
  374.     }
  375.  
  376.     /* Initialise for interpretation */
  377.  
  378.     insertbreak();
  379.     SetExcept(~0, SIGBREAKF_CTRL_C);
  380.     breakset = 1;
  381.     insertftrap();
  382.     ftrapset = 1;
  383.  
  384.     parm.copyfunc = (APTR) copypage;
  385.  
  386.     parm.infh = Input();
  387.     parm.outfh = Output();
  388.     parm.errfh = errfh;
  389.  
  390.     arec = PScreateact(&parm);
  391.     if (arec == 0)
  392.     {   fprintf(stderr, "postlj: can't get memory\n");
  393.         goto errorexit;
  394.     }
  395.     if ((unsigned) arec <= errmax)
  396.     {   arec = 0;
  397.         retcode = 10;
  398.         goto tidyexit;
  399.     }
  400.  
  401.     /* Interpret the argument files */
  402.  
  403.     fprintf(stderr, "postlj: running (%s, %s)\n",
  404.             showsize[optsize], showland[optland]);
  405.  
  406.     pagenum = 0;
  407.     for (i = 0; i < argfilec; i++)
  408.         if (PSintstring(arec, argfilev[i],
  409.                         -1, PSFLAGFILE|PSFLAGCLEAR|PSFLAGERASE) != 0)
  410.         {   retcode = 10;
  411.             goto tidyexit;
  412.         }
  413.  
  414.     if (ferror(parfp))
  415.     {   fprintf(stderr, "postlj: error writing printer file\n");
  416.         goto errorexit;
  417.     }
  418.     fprintf(stderr, "postlj: finished\n");
  419.     goto tidyexit;
  420.  
  421.     /* Argument errors and usage query */
  422.  
  423. badargs:
  424.     fprintf(stderr, "postlj: arguments bad, or value missing\n");
  425.     goto badusage;
  426.  
  427. badvalue:
  428.     fprintf(stderr, "postlj: argument bad value\n");
  429.  
  430. badusage:
  431.     retcode = 20;
  432.  
  433. usage:
  434.     fprintf(stderr, "postlj: usage:\n"
  435.     "    postlj -s.l.b.e.n.c. [files...] [TO tofile] [MEM fhlv..]\n");
  436.     goto tidyexit;
  437.  
  438.     /* Tidy up and exit */
  439.  
  440. errorexit:
  441.     retcode = 20;
  442.  
  443. tidyexit:
  444.     if (breakset)
  445.     {   SetExcept(0, SIGBREAKF_CTRL_C);
  446.         deletebreak();
  447.         breakset = 0;
  448.     }
  449.     if (ftrapset)
  450.     {   deleteftrap();
  451.         ftrapset = 0;
  452.     }
  453.  
  454.     if (arec) PSdeleteact(arec);
  455.  
  456.     if (parfp)
  457.     {   prtreset();
  458.         fclose(parfp);
  459.     }
  460.  
  461.     if (compbuf) FreeMem(compbuf, compsize);
  462.  
  463.     for (i = 0; i < parm.page.depth; i++)
  464.         if (parm.page.buf[i])
  465.         {   FreeMem(parm.page.buf[i], parm.page.len);
  466.             parm.page.buf[i] = NULL;
  467.         }
  468.  
  469.     if (PSbase) CloseLibrary(PSbase);
  470. }
  471.  
  472. /* String to integer conversion; digits only, with error check */
  473.  
  474. int strtoint(char **sp, int *ip)
  475. {   char *s = *sp;
  476.     int i = 0;
  477.     int ch;
  478.     for (;;)
  479.     {   ch = *s;
  480.         if (ch < '0' || ch > '9') break;
  481.         i = i * 10 + (ch - '0');
  482.         s++;
  483.     }
  484.     if (s == *sp)
  485.         return 0;
  486.     else
  487.     {   *sp = s;
  488.         *ip = i;
  489.         return 1;
  490.     }
  491. }
  492.  
  493. /* Signal an interrupt */
  494.  
  495. void __saveds sigint()
  496. {   PSsignalint(arec, 1);
  497. }
  498.  
  499. /* Signal a floating point error */
  500.  
  501. void __saveds sigfpe()
  502. {   PSsignalfpe(arec);
  503. }
  504.  
  505. /* Copy the page to the output */
  506.  
  507. void __saveds __asm copypage(register __d0 int num)
  508. {   pagenum++;
  509.     if ((optbeg == 0 || pagenum >= optbeg) &&
  510.         (optend == 0 || pagenum <= optend))
  511.     {   prtdump(optcopies == 0 ? num : optcopies);
  512.         if (ferror(parfp)) PSerror(arec, errioerror);
  513.     }
  514. }
  515.  
  516. /* Printer setup */
  517.  
  518. void prtsetup(void)
  519. {
  520.     /* Printer reset, Page size, Orientation, Perf skip off, Top Mgn 0 */
  521.  
  522.     fprintf(parfp, "\33E\33&l%da%do0l0E", psize[optsize], optland);
  523.  
  524.     /* Long edge offset, Short edge offset */
  525.  
  526.     if (optland)
  527.         fprintf(parfp, "\33&l%dz%dU",
  528.                 -(150 - ploff[optsize] * 720) / 300, 0);
  529.     else
  530.         fprintf(parfp, "\33&l%du%dZ",
  531.                  (150 - ppoff[optsize] * 720) / 300, 0);
  532. }
  533.  
  534. /* Printer reset */
  535.  
  536. void prtreset(void)
  537. {   fprintf(parfp, "\33E");
  538. }
  539.  
  540. /* Printer dump */
  541.  
  542. void prtdump(int num)
  543. {   char *buf;
  544.     int ysize;
  545.  
  546.     /* Set the number of copies */
  547.  
  548.     if (num == 0 || num > 99) num = 1;
  549.     fprintf(parfp, "\33&l%dX", num);
  550.  
  551.     /* Set cursor to (0,0), 300 dpi, aligned logical page, start graphics */
  552.  
  553.     fprintf(parfp, "\33*p0x0Y\33*t300R\33*r0f0A");
  554.  
  555.     /* Loop for the rows */
  556.  
  557.     buf = parm.page.buf[0];
  558.     ysize = parm.page.ysize;
  559.  
  560.     while (ysize--)
  561.     {   prtdumpline(buf, parm.page.xbytes);
  562.         buf += parm.page.xbytes;
  563.     }
  564.  
  565.     /* End graphics, form feed, reset number of copies */
  566.  
  567.     fprintf(parfp, "\33*rB\14\33&l1X");
  568. }
  569.  
  570. /* Dump a line of pixels */
  571.  
  572. void prtdumpline(char *buf, int len)
  573. {   char *ptr;
  574.     int b, c, l;
  575.  
  576.     /* Strip trailing zeros */
  577.  
  578.     while (len && buf[len - 1] == 0) len--;
  579.  
  580.     /* Compression */
  581.  
  582.     if (optcomp)
  583.     {   ptr = compbuf;
  584.         l = 0;
  585.         while (len--)
  586.         {   b = *buf++;                  /* Pick up a byte */
  587.             c = 1;
  588.             while (len && *buf == b && c < 128)
  589.             {   c++;
  590.                 buf++;
  591.                 len--;                   /* See if it begins a run */
  592.             }
  593.             if (c == 2 &&                /* If a two byte run */
  594.                 l > 0 &&                 /*  and preceeded by literals */
  595.                 l <= 125 &&              /*  and not more than 125 of them */
  596.                 (len <= 2 ||             /*  and no more than 2 bytes left */
  597.                  *buf != *(buf + 1)))    /*      or not followed by a run */
  598.             {   c = 1;                   /* Then make it a literal */
  599.                 buf--;
  600.                 len++;
  601.             }
  602.             if (c == 1)                  /* If not a run */
  603.             {   l++;                     /* Then it must be a literal */
  604.                 c = 0;
  605.             }
  606.             if (l > 0 &&                 /* If we have some literals */
  607.                 (c > 1 ||                /*  and beginning a run */
  608.                  l == 127 ||             /*  or reached 127 */
  609.                  len == 0))              /*  or no more bytes left */
  610.             {   *ptr++ = l - 1;          /* Then write out the literals */
  611.                 memcpy(ptr, buf - c - l, l);
  612.                 ptr += l;
  613.                 l = 0;
  614.             }
  615.             if (c > 1)                   /* If we have a run */
  616.             {   *ptr++ = 1 - c;          /* Then write it */
  617.                 *ptr++ = b;
  618.             }
  619.         }
  620.         len = ptr - compbuf;
  621.         fprintf(parfp, "\33*b2m%dW", len);
  622.         buf = compbuf;
  623.     }
  624.  
  625.     /* No compression */
  626.  
  627.     else
  628.         fprintf(parfp, "\33*b%dW", len);
  629.  
  630.     fwrite(buf, 1, len, parfp);
  631. }
  632.  
  633. /* Dummy stub routine */
  634.  
  635. void stub(void)
  636. {   return;
  637. }
  638.  
  639. /* Dummy check abort routine */
  640.  
  641. void chkabort(void)
  642. {   return;
  643. }
  644.  
  645. /* End of file "postlj.c" */
  646.